﻿// Copyright (c) 2012 - 2020 Jared Zheng <jaredz at outlook dot com>
// Buddha Framework is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
//          http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
//
// Create : 2012-12-01 version 0.1 Jared Zheng <jaredz at outlook dot com>
// Update : 2018-12-05 version 3.1.5 Jared Zheng <jaredz at outlook dot com>

#ifndef __SERVICE_SERVER_IMP_H__
#define __SERVICE_SERVER_IMP_H__

#pragma once

#include "commonpacket.h"
#include "CommonServer.h"
#include "CommonRoutine.h"

///////////////////////////////////////////////////////////////////////////////////////////////////////////
/// 业务功能服务器实现
class CServiceServer : public ICommonServer, public CPAKHandler
{
public:
    CServiceServer(void);
    virtual ~CServiceServer(void);
    // CComponent
    // Command to set param value
    virtual UInt   Command(PCXStr pszCMD, uintptr_t utParam) OVERRIDE;
    virtual UInt   Update(void) OVERRIDE;

    virtual UInt   Init(CEventHandler& EventHandlerRef, CServerConfig& ConfigRef) OVERRIDE;
    virtual void   Exit(void) OVERRIDE;

    virtual bool   Start(void) OVERRIDE;
    virtual bool   Pause(bool bPause = true) OVERRIDE;
    virtual void   Stop(void) OVERRIDE;
    // CPAKHandler
    virtual bool   OnTcpDispatch(const PacketPtr& PktPtr, PTCP_PARAM pTcp) OVERRIDE;
    virtual bool   OnUdpDispatch(const PacketPtr& PktPtr, PUDP_PARAM pUdp) OVERRIDE;//
    virtual bool   OnTcpAccept(Socket sAccept, Socket sListen) OVERRIDE;//
    virtual bool   OnTcpConnect(UInt uError, Socket sConnect) OVERRIDE;
    virtual bool   OnTcpRecv(size_t stSize, PTCP_PARAM pTcp) OVERRIDE;//
    virtual bool   OnTcpSend(UInt uQueueLimit, Socket sSocket) OVERRIDE;//
    virtual bool   OnTcpClose(Socket sSocket, ULLong ullLiveData) OVERRIDE;

    virtual bool   OnUdpRecv(size_t stSize, PUDP_PARAM pUdp) OVERRIDE;//
    virtual bool   OnUdpSend(UInt uQueueLimit, Socket sSocket) OVERRIDE;//
    virtual bool   OnUdpClose(Socket sSocket, ULLong ullLiveData) OVERRIDE;//
    // Routine
    virtual Socket_t          GetSocket(UInt uType) OVERRIDE;
    virtual PSERVER_INFO      GetServerInfo(UInt uType) OVERRIDE;
    virtual PSVR_COMMON_MAP   GetServerMap(UInt uType) OVERRIDE;
    virtual PRESULT_CHAIN     GetServerSort(UInt uType) OVERRIDE;
    virtual CServerConfig&    GetConfig(void) OVERRIDE;
    virtual CFileLog&         GetFileLog(void) OVERRIDE;
    virtual CEventHandlerPtr& GetMgrHandler(void) OVERRIDE;
    virtual CNetworkPtr&      GetNetworkPtr(void) OVERRIDE;
private:
    CServiceServer(const CServiceServer&);
    CServiceServer& operator=(const CServiceServer&);
    /// 配置相关
    bool  LoadConfig(void);
    void  UnloadConfig(void);

    bool  StartConnectMasterServer(void);
    bool  StartConnectMasterDBServer(void);

    bool  CheckConnectMasterServer(void);
    bool  CheckConnectMasterDBServer(void);

    void  StopConnectMasterServer(void);
    void  StopConnectMasterDBServer(void);

    /// 向业务管理服务器注册/注销
    void  LinkMasterServer(void);
    void  UnlinkMasterServer(void);
    /// 向业务数据服务器注册/注销
    void  LinkMasterDBServer(void);
    void  UnlinkMasterDBServer(void);

    /// 处理业务管理服务器的信令包
    bool  DispatchMasterServer(const PacketPtr& PktPtr, PTCP_PARAM pTcp);
    /// 处理业务数据服务器的信令包
    bool  DispatchMasterDBServer(const PacketPtr& PktPtr, PTCP_PARAM pTcp);

    /// 同步服务器信息给控制台
    bool  SyncServerInfo(void);

    bool  LoadExtConfig(void);
    bool  LoadExtRoutine(CKVNode& Root);
    bool  CreateRTTIObject(PCXStr pszObject, PCXStr pszName, PCXStr pszModule);
    bool  UnloadExtConfig(void);
    bool  UnloadExtRoutine(void);
private:
    Int                 m_nStatus;           ///< 服务器状态
    Int                 m_nMasterLink;       ///< 连接业务管理服务器状态
    Int                 m_nMasterDBLink;     ///< 连接业务数据服务器状态
    // 框架例程开关, 由框架例程通过调用Command修改服务器实例对应参数
    Int                 m_nServerAck;         ///< 例程需要处理连接上服务器ACK信息PAKE_LINKACK/PAKE_UNLINKACK
    Int                 m_nSyncInfo;          ///< 例程需要处理服务器PAKE_LINK/PAKE_UPDATE同步信息时增加其他数据
    Int                 m_nCommonEvent;       ///< 例程需要处理服务器内部通用PAKE_COMMON_BEGIN/PAKE_COMMON_END事件
    //
    CServerConfig*      m_pConfig;           ///< 配置
    Socket              m_sConnectMaster;    ///< 内网, 连接业务管理服务器
    Socket              m_sConnectMasterDB;  ///< 内网, 连接业务数据服务器
    CFileLog            m_FileLog;           ///< 简单文本日志
    CEventHandlerPtr    m_MgrHandler;        ///< 控制台回调接口
    CNetworkPtr         m_NetworkPtr;        ///< 网络
    CCommonRoutinePtr   m_RoutinePtr;        ///< 例程处理 
    SERVICE_ADDR        m_ServerInfo;        ///< 本服务器信息
};

INLINE CServiceServer::CServiceServer(void)
: m_nStatus(STATUSS_NONE)
, m_nMasterLink(STATUSL_NONE)
, m_nMasterDBLink(STATUSL_NONE)
, m_nServerAck(TRUE)
, m_nSyncInfo(FALSE)
, m_nCommonEvent(FALSE)
, m_pConfig(nullptr)
, m_sConnectMaster(0)
, m_sConnectMasterDB(0)
, m_FileLog(false)
{
}

INLINE CServiceServer::~CServiceServer(void)
{
}

INLINE CServiceServer::CServiceServer(const CServiceServer&)
: m_nStatus(STATUSS_NONE)
, m_nMasterLink(STATUSL_NONE)
, m_nMasterDBLink(STATUSL_NONE)
, m_nServerAck(TRUE)
, m_nSyncInfo(FALSE)
, m_nCommonEvent(FALSE)
, m_pConfig(nullptr)
, m_sConnectMaster(0)
, m_sConnectMasterDB(0)
, m_FileLog(false)
{
}

INLINE CServiceServer& CServiceServer::operator=(const CServiceServer&)
{
    return (*this);
}

INLINE bool CServiceServer::OnUdpDispatch(const PacketPtr&, PUDP_PARAM)
{
    // 1. PUDP_PARAM->pCache != nullptr时上层可以保存网络层申请的缓存数据
    //    PUDP_PARAM->pCache, PUDP_PARAM->index是网络层申请的缓存数据的起始地址和索引号
    // 2. PUDP_PARAM->pData为当前数据开始地址, PUDP_PARAM->stSize为当前数据大小
    // 3. 如果上层保存缓存, 设置PUDP_PARAM->pData为nullptr通知网络层不要再使用当前缓存
    // 4. 释放缓存使用MObject::sMCFree(index, pCache)
    return false;
}

INLINE bool CServiceServer::OnTcpAccept(Socket, Socket)
{
    return false;
}

INLINE bool CServiceServer::OnTcpRecv(size_t, PTCP_PARAM)
{
    return false;
}

INLINE bool CServiceServer::OnTcpSend(UInt, Socket)
{
    return true;
}

INLINE bool CServiceServer::OnUdpRecv(size_t, PUDP_PARAM)
{
    return false;
}

INLINE bool CServiceServer::OnUdpSend(UInt, Socket)
{
    return true;
}

INLINE bool CServiceServer::OnUdpClose(Socket, ULLong)
{
    return false;
}

INLINE uintptr_t CServiceServer::GetSocket(UInt uType)
{
    if (uType == PAKT_MASTER)
    {
        return m_sConnectMaster;
    }
    return m_sConnectMasterDB;
}

INLINE PSERVER_INFO CServiceServer::GetServerInfo(UInt)
{
    return &m_ServerInfo;
}

INLINE PSVR_COMMON_MAP CServiceServer::GetServerMap(UInt)
{
    return nullptr;
}

INLINE PRESULT_CHAIN CServiceServer::GetServerSort(UInt)
{
    return nullptr;
}

INLINE CServerConfig& CServiceServer::GetConfig(void)
{
    return (*m_pConfig);
}

INLINE CFileLog& CServiceServer::GetFileLog(void)
{
    return m_FileLog;
}

INLINE CEventHandlerPtr& CServiceServer::GetMgrHandler(void)
{
    return m_MgrHandler;
}

INLINE CNetworkPtr& CServiceServer::GetNetworkPtr(void)
{
    return m_NetworkPtr;
}

#endif // __SERVICE_SERVER_IMP_H__
